﻿using System;
using System.Net;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SpaceInvaderz
{
    public class Enviroment
    {
        GameCore _gameCore;


        public Enviroment(GameCore gameCore)
        {
            Projectiles = new List<Sprite>();
            Allies = new List<Sprite>();
            Enemies = new List<Sprite>();
            PowerUps = new List<Sprite>();
            Effects = new List<Sprite>();
            Shields = new List<Sprite>();
            _gameCore = gameCore;
        }

        public void Update(double gameTime, double lastTime)
        {
            UpdateEnemies(gameTime, lastTime);
            UpdatePowerUps(gameTime, lastTime);
            UpdateProjectiles(gameTime, lastTime);
            UpdateAllies(gameTime, lastTime);
            UpdateEffects(gameTime, lastTime);
        }

        private void UpdateEffects(double gameTime, double lastTime)
        {
            for (int i = Effects.Count - 1; i >= 0; i--)
            {
                if (i >= Effects.Count)
                    break;

                if (Effects[i].Hp <= 0)
                {
                    Effects[i].Kill();
                    Effects.RemoveAt(i);
                    continue;
                }

                Effects[i].Update(gameTime, lastTime);
            }
        }

        public void UpdateEnemies(double gameTime, double lastTime)
        {
            for (int i = Enemies.Count - 1; i >= 0; i--)
            {
                if (i >= Enemies.Count)
                    break;




                if (Enemies[i].Hp <= 0)
                {
                    BigExplode(Enemies[i].LocationX, Enemies[i].LocationY);
                    _gameCore._page.Explosion.Stop();
                    _gameCore._page.Explosion.Play();
                    _gameCore.Points += 50;

                    Enemies[i].Kill();
                    Enemies.RemoveAt(i);
                    Spawn();
                    continue;
                }

                for (int j = Enemies.Count - 1; j >= 0; j--)
                {
                    if (j >= Enemies.Count)
                        break;
                    if (i == j)
                        continue;


                    if (Sprite.Collision(Enemies[i], Enemies[j]))
                    {
                        Enemies[j].Hp = 0;
                        continue;
                    }
                }

                Enemies[i].Update(gameTime, lastTime);


                if (Enemies[i].LocationX < -100)
                {
                    Enemies[i].Kill();
                    Enemies.RemoveAt(i);
                    Spawn();
                    Spawn();
                    continue;
                }


                for (int j = Projectiles.Count - 1; j >= 0; j--)
                {
                    if (j >= Projectiles.Count)
                        break;
                    if (Sprite.Collision(Projectiles[j], Enemies[i]._shield) && Enemies[i]._shield.Hp > 0)
                    {
                        Enemies[i]._shield.Hp -= Projectiles[j].Attack;
                        LittleExplode(Projectiles[j].LocationX, Projectiles[j].LocationY, Enemies[i].VelocityX);
                        Projectiles[j].Kill();
                        Projectiles.RemoveAt(j);

                        break;
                    }

                }

                for (int j = Projectiles.Count - 1; j >= 0; j--)
                {
                    if (j >= Projectiles.Count)
                        break;
                    if (Sprite.Collision(Projectiles[j], Enemies[i]))
                    {
                        Enemies[i].Hp -= Projectiles[j].Attack;
                        LittleExplode(Projectiles[j].LocationX, Projectiles[j].LocationY, Enemies[i].VelocityX);
                        Projectiles[j].Kill();
                        Projectiles.RemoveAt(j);

                        break;
                    }

                }

            }
        }

        public void UpdatePowerUps(double gameTime, double lastTime)
        {
            for (int i = PowerUps.Count - 1; i >= 0; i--)
            {
                if (i >= PowerUps.Count)
                    break;

                if (PowerUps[i].Hp <= 0)
                {
                    _gameCore.Points += 60;
                    Power(PowerUps[i]);
                    PowerUps[i].Kill();
                    PowerUps.RemoveAt(i);
                    continue;
                }

                if (Sprite.Collision(PowerUps[i], _gameCore._hero))
                {
                    Power(PowerUps[i]);
                    PowerUps[i].Kill();
                    PowerUps.RemoveAt(i);
                    continue;
                }

                PowerUps[i].Update(gameTime, lastTime);
            }
        }

        private void Power(Sprite powerup)
        {
            switch (powerup.function)
            {
                case (PowerUpFunction.Health):
                    _gameCore._hero.Hp += 1;
                    break;

                case (PowerUpFunction.Shields):
                    _gameCore._page.ShieldUp.Stop();
                    _gameCore._page.ShieldUp.Play();
                    if (_gameCore._hero._shield.Hp <= 0 && _gameCore._hero._shield._visual.Visibility == Visibility.Collapsed)
                    {
                        _gameCore._hero._page.myCanvas.Children.Add(_gameCore._hero._shield._visual);
                        _gameCore._hero._shield.Hp = 2;
                        _gameCore._hero._shield.VelocityX = _gameCore._hero.VelocityX;
                        _gameCore._hero._shield.VelocityY = _gameCore._hero.VelocityY;
                        _gameCore._hero._shield.LocationX = _gameCore._hero.LocationX;
                        _gameCore._hero._shield.LocationY = _gameCore._hero.LocationY;
                        _gameCore._hero._page.gameCore._enviroment.Shields.Add(_gameCore._hero._shield);
                        _gameCore._hero._shield._visual.Visibility = Visibility.Visible;
                    }
                    break;

                case (PowerUpFunction.Speed):
                    _gameCore.Speed += 50;
                    break;

                default:
                    break;
            }
        }

        public void UpdateAllies(double gameTime, double lastTime)
        {
            for (int i = Allies.Count - 1; i >= 0; i--)
            {
                if (i >= Allies.Count)
                    break;

                if (Allies[i].Hp <= 0)
                {
                    Allies[i].Kill();
                    Allies.RemoveAt(i);
                    continue;
                }

                Allies[i].Update(gameTime, lastTime);
            }
        }

        public void UpdateShields(double gameTime, double lastTime)
        {
            for (int i = Shields.Count - 1; i >= 0; i--)
            {
                if (i >= Shields.Count)
                    break;

                if (Shields[i].Hp <= 0)
                {
                    Shields[i].Kill();
                    Shields.RemoveAt(i);
                    _gameCore._page.ShieldDown.Stop();
                    _gameCore._page.ShieldDown.Play();
                    continue;
                }

                Shields[i].Update(gameTime, lastTime);
            }
        }

        public void UpdateProjectiles(double gameTime, double lastTime)
        {
            for (int i = Projectiles.Count - 1; i >= 0; i--)
            {
                if (i >= Projectiles.Count)
                    break;

                if (Projectiles[i].Hp <= 0)
                {
                    LittleExplode(Projectiles[i].LocationX, Projectiles[i].LocationY, 0);
                    Projectiles[i].Kill();
                    Projectiles.RemoveAt(i);

                    continue;
                }

                Projectiles[i].Update(gameTime, lastTime);
                if (Projectiles[i].LocationX > 3000)
                {
                    Projectiles[i].Kill();
                    Projectiles.RemoveAt(i);

                    continue;
                }
            }
        }

        public List<Sprite> Enemies
        {
            get;
            set;
        }

        public List<Sprite> Allies
        {
            get;
            set;
        }

        public List<Sprite> Projectiles
        {
            get;
            set;
        }

        public List<Sprite> PowerUps
        {
            get;
            set;
        }

        public List<Sprite> Effects
        {
            get;
            set;
        }

        public List<Sprite> Shields
        {
            get;
            set;
        }

        public void Spawn()
        {
            if (Enemies.Count <= 20)
            {
                Random rrr = new Random();
                Random x = new Random(rrr.Next());
                Random z = new Random(x.Next());
                Sprite enemy = new Sprite(100, 100, @"SpaceInvaderz;component/Images/Enemy.png", _gameCore._page);
                enemy._visual.Visibility = Visibility.Collapsed;
                enemy.LocationX = x.Next((int)_gameCore._worldLimits.X + 500, (int)_gameCore._worldLimits.X + 1500);
                enemy.LocationY = rrr.Next((int)_gameCore._worldLimits.Y/* - 100*/);
                enemy.VelocityX = x.Next(-200, -100);
                enemy.VelocityY = z.Next(-100, 100);
                enemy._visual.SetValue(Canvas.LeftProperty, enemy.LocationX);
                enemy._visual.SetValue(Canvas.TopProperty, enemy.LocationY);
                enemy.Hp = 1;
                enemy._shield = new Sprite(150, 150, @"SpaceInvaderz;component/Images/BigShield.png", _gameCore._page);
                enemy._shield.Hp = 2;
                enemy._shield.VelocityX = enemy.VelocityX;
                enemy._shield.VelocityY = enemy.VelocityY;
                enemy._shield.LocationX = enemy.LocationX;
                enemy._shield.LocationY = enemy.LocationY;
                enemy._shield._visual.SetValue(Canvas.LeftProperty, enemy.LocationX);
                enemy._shield._visual.SetValue(Canvas.TopProperty, enemy.LocationY);
                enemy.Attack = 1;
                enemy._visual.Visibility = Visibility.Visible;

                Enemies.Add(enemy);
            }
        }

        public void Shoot()
        {
            if (Projectiles.Count < 5)
            {
                Sprite shot = new Sprite(10, 10, @"SpaceInvaderz;component/Images/Shot.png", _gameCore._page);
                shot._visual.Visibility = Visibility.Collapsed;
                shot.LocationX = _gameCore._hero.LocationX + _gameCore._hero._visual.Width + 2;
                shot.LocationY = _gameCore._hero.LocationY + (_gameCore._hero._visual.Height / 2);
                shot.VelocityX = 200;
                shot._visual.SetValue(Canvas.LeftProperty, shot.LocationX);
                shot._visual.SetValue(Canvas.TopProperty, shot.LocationY);
                shot._visual.Visibility = Visibility.Visible;
                shot.Attack = 1;
                Projectiles.Add(shot);
            }
        }

        public void BigExplode(double x, double y)
        {
            Sprite shot = new Sprite(100, 100, @"SpaceInvaderz;component/Images/BigExplosion.png", _gameCore._page);
            shot._visual.Visibility = Visibility.Collapsed;
            shot.LocationX = x;
            shot.LocationY = y;
            shot._visual.SetValue(Canvas.LeftProperty, shot.LocationX);
            shot._visual.SetValue(Canvas.TopProperty, shot.LocationY);
            shot._visual.Visibility = Visibility.Visible;
            shot.LifeTime = 10;
            Effects.Add(shot);
        }

        public void LittleExplode(double x, double y, double velocity)
        {
            Sprite shot = new Sprite(10, 10, @"SpaceInvaderz;component/Images/LittleExplosion.png", _gameCore._page);
            shot._visual.Visibility = Visibility.Collapsed;
            shot.LocationX = x;
            shot.LocationY = y;
            shot._visual.SetValue(Canvas.LeftProperty, shot.LocationX);
            shot._visual.SetValue(Canvas.TopProperty, shot.LocationY);
            shot.VelocityX = velocity;
            shot._visual.Visibility = Visibility.Visible;
            shot.LifeTime = 10;
            Effects.Add(shot);
        }

        public void SpeedPack(double x, double y)
        {
            Sprite pwr = new Sprite(50, 50, @"SpaceInvaderz;component/Images/SpeedPack.png", _gameCore._page);
            pwr.function = PowerUpFunction.Speed;
            pwr.LocationX = x;
            pwr.LocationY = y;
            pwr._visual.SetValue(Canvas.LeftProperty, pwr.LocationX);
            pwr._visual.SetValue(Canvas.TopProperty, pwr.LocationY);
            PowerUps.Add(pwr);
        }

        public void HealthPack(double x, double y)
        {
            Sprite pwr = new Sprite(50, 50, @"SpaceInvaderz;component/Images/HealthPack.png", _gameCore._page);
            pwr.function = PowerUpFunction.Health;
            pwr.LocationX = x;
            pwr.LocationY = y;
            pwr._visual.SetValue(Canvas.LeftProperty, pwr.LocationX);
            pwr._visual.SetValue(Canvas.TopProperty, pwr.LocationY);
            PowerUps.Add(pwr);
        }

        public void ShieldPack(double x, double y)
        {
            Sprite pwr = new Sprite(50, 50, @"SpaceInvaderz;component/Images/ShieldPack.png", _gameCore._page);
            pwr.function = PowerUpFunction.Shields;
            pwr.LocationX = x;
            pwr.LocationY = y;
            pwr._visual.SetValue(Canvas.LeftProperty, pwr.LocationX);
            pwr._visual.SetValue(Canvas.TopProperty, pwr.LocationY);
            PowerUps.Add(pwr);
        }
    }
}
